﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using Telerik.Sitefinity.Libraries.Model;
using Telerik.Sitefinity.Modules.Libraries;
using Telerik.Sitefinity.GenericContent.Model;
using Telerik.Sitefinity.Security;
using Telerik.Sitefinity.Security.Model;
using Telerik.Sitefinity.Workflow;
using Telerik.Sitefinity.SitefinityExceptions;

namespace Migration.Classes
{
	public static class MigrationLibraries
	{
		private static LibrariesManager m_LibrariesManager;

		static MigrationLibraries()
		{
			m_LibrariesManager = LibrariesManager.GetManager(MigrationSettings.LibrariesProvider);
		}

		private static void CheckProvider()
		{
			if (m_LibrariesManager.Provider == null || MigrationSettings.ApplicationRestarted)
			{
				m_LibrariesManager = LibrariesManager.GetManager(MigrationSettings.LibrariesProvider);
			}
		}

        public static void AddPermissionsToLibrary(Library library)
        {
            string permSet = String.Empty;
            string[] actionsAllowedForEveryone = null;
            string[] actionsAllowedForBackendUsers = null;
            string[] actionsAllowedForOwners = null;

            if (library as Album != null)
            {
                permSet = SecurityConstants.Sets.Album.SetName;
                actionsAllowedForEveryone = new string[] { SecurityConstants.Sets.Album.View };
                actionsAllowedForBackendUsers = new string[] { SecurityConstants.Sets.Album.Create, SecurityConstants.Sets.Album.Delete };
                actionsAllowedForOwners = new string[] { SecurityConstants.Sets.Album.ChangePermissions };
            }
            else if (library as DocumentLibrary != null)
            {
                permSet = SecurityConstants.Sets.DocumentLibrary.SetName;
                actionsAllowedForEveryone = new string[] { SecurityConstants.Sets.DocumentLibrary.View };
                actionsAllowedForBackendUsers = new string[] { SecurityConstants.Sets.DocumentLibrary.Create, SecurityConstants.Sets.DocumentLibrary.Delete };
                actionsAllowedForOwners = new string[] { SecurityConstants.Sets.DocumentLibrary.ChangePermissions };
            }
            else if (library as VideoLibrary != null)
            {
                permSet = SecurityConstants.Sets.VideoLibrary.SetName;
                actionsAllowedForEveryone = new string[] { SecurityConstants.Sets.VideoLibrary.View };
                actionsAllowedForBackendUsers = new string[] { SecurityConstants.Sets.VideoLibrary.Create, SecurityConstants.Sets.VideoLibrary.Delete };
                actionsAllowedForOwners = new string[] { SecurityConstants.Sets.VideoLibrary.ChangePermissions };
            }

            Telerik.Sitefinity.Security.Model.Permission permissionForEveryone = m_LibrariesManager.CreatePermission(permSet, ((ISecuredObject)library).Id, SecurityManager.ApplicationRoles["Everyone"].Id);
            permissionForEveryone.GrantActions(true, actionsAllowedForEveryone);

            Telerik.Sitefinity.Security.Model.Permission permissionForBackendUsers = m_LibrariesManager.CreatePermission(permSet, ((ISecuredObject)library).Id, SecurityManager.ApplicationRoles["BackendUsers"].Id);
            permissionForBackendUsers.GrantActions(true, actionsAllowedForBackendUsers);

            Telerik.Sitefinity.Security.Model.Permission permissionForOwners = m_LibrariesManager.CreatePermission(permSet, ((ISecuredObject)library).Id, SecurityManager.OwnerRole.Id);
            permissionForOwners.GrantActions(true, actionsAllowedForOwners);

            ((ISecuredObject)library).Permissions.Add(permissionForEveryone);
            ((ISecuredObject)library).Permissions.Add(permissionForBackendUsers);
            ((ISecuredObject)library).Permissions.Add(permissionForOwners);
        }

		public static Library GetLibrary(Guid id)
		{
			CheckProvider();

			var checkAlbum = m_LibrariesManager.GetAlbums().Where(t => t.Id == id).FirstOrDefault();
			var checkDocumentLib = m_LibrariesManager.GetDocumentLibraries().Where(t => t.Id == id).FirstOrDefault();
			var checkVideoLib = m_LibrariesManager.GetVideoLibraries().Where(t => t.Id == id).FirstOrDefault();

			if (checkAlbum != null)
				return checkAlbum;
			else if (checkDocumentLib != null)
				return checkDocumentLib;
			else if (checkVideoLib != null)
				return checkVideoLib;
			else
				return null;
		}

		public static void ImportLibrary(Telerik.Sitefinity.Services.Migration.MigrationLibrary libraryContent, string type)
		{
			CheckProvider();

			Guid id = libraryContent.Id;
			string name = libraryContent.Name;

			Library libraryItem;

			var checkItem = MigrationLibraries.GetLibrary(libraryContent.Id);
			if (checkItem != null)
			{
				MigrationLogger.AppendLogMessage(String.Format("Resuming {0} library \"<b>{1}</b>\" with <b>{2}</b> item(s)...", type.ToLowerInvariant(), name, libraryContent.Documents.Count));

				libraryItem = checkItem;
			}
			else
			{
				MigrationLogger.AppendLogMessage(String.Format("Importing {0} library \"<b>{1}</b>\" with <b>{2}</b> item(s)...", type.ToLowerInvariant(), name, libraryContent.Documents.Count));

				if (type == "Image")
					libraryItem = m_LibrariesManager.CreateAlbum(id);
				else if (type == "Document")
					libraryItem = m_LibrariesManager.CreateDocumentLibrary(id);
				else if (type == "Video")
					libraryItem = m_LibrariesManager.CreateVideoLibrary(id);
				else
					libraryItem = m_LibrariesManager.CreateDocumentLibrary(id);

				libraryItem.DateCreated = libraryContent.DateCreated;
				libraryItem.MaxItemSize = (int)libraryContent.MaxSize;
				libraryItem.MaxSize = (int)libraryContent.MaxSize;

				if (MigrationCultures.IsMultilingual)
				{
					libraryItem.Title[MigrationCultures.DefaultCulture] = name;
					libraryItem.UrlName[MigrationCultures.DefaultCulture] = MigrationUtils.GetUrlName(name);
				}
				else
				{
					libraryItem.Title = name;
					libraryItem.UrlName = MigrationUtils.GetUrlName(name);
				}

				libraryItem.Owner = MigrationUsers.DefaultOwner;
				//if (type == "Image")
				//	((Album)libraryItem).ResizeOnUpload = true;
				libraryItem.UIStatus = ContentUIStatus.Published;

				if (type == "Image")
					m_LibrariesManager.RecompileItemUrls<Album>((Album)libraryItem);
				else if (type == "Document")
					m_LibrariesManager.RecompileItemUrls<DocumentLibrary>((DocumentLibrary)libraryItem);
				else if (type == "Video")
					m_LibrariesManager.RecompileItemUrls<VideoLibrary>((VideoLibrary)libraryItem);
				else
					m_LibrariesManager.RecompileItemUrls<DocumentLibrary>((DocumentLibrary)libraryItem);

				AddPermissionsToLibrary(libraryItem);

				m_LibrariesManager.SaveChanges();
			}

			foreach (Telerik.Sitefinity.Services.Migration.MigrationGenericContent libraryDocument in libraryContent.Documents)
			{
				MediaContent libraryItemDocument;

				if (type == "Image")
				{
					// Check if this image was already imported
					Image checkImage = null;

					try
					{
						checkImage = m_LibrariesManager.GetImage(libraryDocument.Id);
					}
					catch (ItemNotFoundException) { }

					if (checkImage != null)
					{
						continue;
					}

					libraryItemDocument = m_LibrariesManager.CreateImage(libraryDocument.Id);
				}
				else if (type == "Document")
				{
					// Check if this document was already imported
					Document checkDocument = null;
					
					try
					{
						checkDocument = m_LibrariesManager.GetDocument(libraryDocument.Id);
					}
					catch (ItemNotFoundException) { }

					if (checkDocument != null)
					{
						continue;
					}

					libraryItemDocument = m_LibrariesManager.CreateDocument(libraryDocument.Id);
				}
				else if (type == "Video")
				{
					// Check if this video was already imported
					Video checkVideo = null;

					try
					{
						checkVideo = m_LibrariesManager.GetVideo(libraryDocument.Id);
					}
					catch (ItemNotFoundException) { }

					if (checkVideo != null)
					{
						continue;
					}

					libraryItemDocument = m_LibrariesManager.CreateVideo(libraryDocument.Id);
				}
				else
				{
					// Check if this document was already imported
					Document checkDocument = null;
					try
					{
						checkDocument = m_LibrariesManager.GetDocument(libraryDocument.Id);
					}
					catch (ItemNotFoundException) { }

					if (checkDocument != null)
					{
						continue;
					}

					libraryItemDocument = m_LibrariesManager.CreateDocument(libraryDocument.Id);
				}

				libraryItemDocument.Parent = libraryItem;
				libraryItemDocument.DateCreated = libraryDocument.DateCreated;
				libraryItemDocument.LastModified = libraryDocument.DateModified;
				libraryItemDocument.Owner = MigrationUsers.DefaultOwner;
				libraryItemDocument.UIStatus = ContentUIStatus.Published;
				libraryItemDocument.MimeType = libraryDocument.MimeType;

				foreach (KeyValuePair<string, object> metaData in libraryDocument.MetaData)
				{
					if (metaData.Value == null)
						continue;

					switch (metaData.Key)
					{
						case "Author":
							if (MigrationCultures.IsMultilingual)
								libraryItemDocument.Author[MigrationCultures.DefaultCulture] = metaData.Value.ToString();
							else
								libraryItemDocument.Author = metaData.Value.ToString();
							break;
						case "AlternateText":
							if (type == "Image")
							{
								if (MigrationCultures.IsMultilingual)
									((Image)libraryItemDocument).AlternativeText[MigrationCultures.DefaultCulture] = metaData.Value.ToString();
								else
									((Image)libraryItemDocument).AlternativeText = metaData.Value.ToString();
							}
							break;
						case "Category":
							MigrationTaxonomies.AddCategoryToOrganizer(metaData.Value.ToString(), libraryItemDocument.Organizer, MigrationCultures.DefaultCulture);
							break;
						case "Description":
							if (MigrationCultures.IsMultilingual)
								libraryItemDocument.Description[MigrationCultures.DefaultCulture] = metaData.Value.ToString();
							else
								libraryItemDocument.Description = metaData.Value.ToString();
							break;
						case "Extension":
							libraryItemDocument.Extension = metaData.Value.ToString();
							break;
						case "Height":
							((Image)libraryItemDocument).Height = Int32.Parse(metaData.Value.ToString());
							break;
						case "Name":
							if (MigrationCultures.IsMultilingual)
								libraryItemDocument.Title[MigrationCultures.DefaultCulture] = metaData.Value.ToString();
							else
								libraryItemDocument.Title = metaData.Value.ToString();
							break;
						case "Size":
							libraryItemDocument.TotalSize = Int32.Parse(metaData.Value.ToString());
							break;
						case "Width":
							((Image)libraryItemDocument).Width = Int32.Parse(metaData.Value.ToString());
							break;
					}
				}

				if (MigrationCultures.IsMultilingual)
					libraryItemDocument.UrlName[MigrationCultures.DefaultCulture] = MigrationUtils.GetUrlName(libraryItemDocument.Title);
				else
					libraryItemDocument.UrlName = MigrationUtils.GetUrlName(libraryItemDocument.Title);

				// Add the tags
				MigrationTaxonomies.AddTagsToOrganizer(libraryDocument.Tags, libraryItemDocument.Organizer, MigrationCultures.DefaultCulture);

				// Add file data
				if (libraryDocument.Content != null)
				{
					byte[] imageData = (byte[])libraryDocument.Content;

					using (var imageStream = new MemoryStream(imageData))
					{
						if (imageStream.Length > 0)
						{
							m_LibrariesManager.Upload(libraryItemDocument, imageStream, libraryItemDocument.Extension);

							var masterId = libraryItemDocument.OriginalContentId;

							if (type == "Image")
							{
								m_LibrariesManager.RecompileItemUrls<Image>((Image)libraryItemDocument);
							}
							else if (type == "Document")
							{
								m_LibrariesManager.RecompileItemUrls<Document>((Document)libraryItemDocument);
							}
							else if (type == "Video")
							{
								m_LibrariesManager.RecompileItemUrls<Video>((Video)libraryItemDocument);
							}
							else
							{
								m_LibrariesManager.RecompileItemUrls<Document>((Document)libraryItemDocument);
							}

							if (libraryItemDocument.Status == ContentLifecycleStatus.Master)
							{
                                System.Threading.Thread.CurrentThread.CurrentUICulture = MigrationCultures.DefaultCulture;
								m_LibrariesManager.CheckOut(libraryItemDocument);
								masterId = libraryItemDocument.Id;
							}

							m_LibrariesManager.SaveChanges();

							var contextBag = new Dictionary<string, string>();
							contextBag.Add("ContentType", libraryItemDocument.GetType().FullName);

							WorkflowManager.MessageWorkflow(
								masterId,
								libraryItemDocument.GetType(),
								MigrationSettings.GenericContentProvider,
								"Publish",
								false,
								contextBag);
						}
					}
				}

				// Add the comments
				//MigrationComments.AddCommentsToLibraryItem(libraryItemDocument, libraryDocument.Comments);
			}

			MigrationLogger.AppendLogMessage(String.Format("done.", name));
		}
	}
}
